<template>
  <div>
    <div class="sidebar">
      <img @click="fpsClick" id="fps" class="buttonClass" title="性能调试" src="../icon/fps.svg">
      <img @click="storeClick" id="store" class="buttonClass" title="显示仓库" src="../icon/store.svg">
      <img @click="groupClick" id="group" class="buttonClass" title="显示巷道" src="../icon/group.svg">
      <img @click="shelfClick" id="shelf" class="buttonClass" title="显示架子" src="../icon/shelf.svg">
      <img @click="resetEvent" id="reset" class="buttonClass" title="复位场景" src="../icon/reset.svg">
    </div>
    <div id="canvas-frame">
    </div>
    <div id="S01" style="width: 400px;height: 400px"></div>
    <div id="S02" style="width: 400px;height: 400px"></div>
    <div id="S03" style="width: 400px;height: 400px"></div>
    <div id="S04" style="width: 400px;height: 400px"></div>
    <div id="S05" style="width: 400px;height: 400px"></div>
    <div id="label"></div>


  </div>

</template>

<script>
  import * as THREE from "three";
  import {OrbitControls} from "three/examples/jsm/controls/OrbitControls.js"
  import Stats from "three/examples/jsm/libs/stats.module"
  import {getBuildData} from "../buildData/BuildingData";
  import {StoreArea} from "../building/StoreArea";
  import {getStoreData} from "../api/StoreData";
  import {transPosition} from "../utils/CommonUtils";
  import {Store} from "../building/Store";
  import {StoreShelf} from "../building/StoreShelf";
  import {StoreGroup} from "../api/StoreGroup";
  import * as echarts from "echarts"
  import {Goods,judgmentObject} from "../building/Goods";
  import {initObjectSelect} from "../building/ObjectSelect";
  import {OBJLoader} from "three/examples/jsm/loaders/OBJLoader"
  import {MTLLoader} from "three/examples/jsm/loaders/MTLLoader"
  import {Route,RouteLine} from "../building/Route";
  import {EffectComposer} from "three/examples/jsm/postprocessing/EffectComposer"
  import {OutlinePass} from "three/examples/jsm/postprocessing/OutlinePass"
  import {RenderPass} from "three/examples/jsm/postprocessing/RenderPass"
  import {ShaderPass} from "three/examples/jsm/postprocessing/ShaderPass"
  import {CopyShader} from "three/examples/jsm/shaders/CopyShader"



  var scene;
  var camera;
  var control;
  var stats;
  var renderer;
  var light;
  var amblight;
  var pointLight1;
  var pointLight2;
  var axes;
  var CarObject;//小车对象
  var composer;//效果组合器对象


  export default {
        name: "Csdn",
        components:{},
        props:[],
        data(){
          return{
            Store3DData:[{}],//本地缓存数据
            width:'',
            height:'',
            objects:[],//用来存储场景中有可能需要进行操作的几何体对象
            buildDatas:[],
            storeIsShow:1,//是否显示库房
            groupIsShow:1,//是否显示排
            shelfIsShow:1,//是否显示架子
            catmullRomCurve3:'',//小车移动的路径
            carTime:0,//小车运行时间,
            outlinePass:'',//边框高亮通道对象
            renderPass:'',//渲染通道对象
          }
        },
        computed:{},
        watch:{},
        created() {
        },
        mounted() {
          this.width=document.getElementById("canvas-frame").clientWidth;
          this.height=document.getElementById("canvas-frame").clientHeight;
          this.threeStart();
        },
        methods: {
          threeStart(){

            //初始化渲染器
            this.initThree();
            //初始化场景
            this.initScene();
            //初始化相机
            this.initCamera();
            //初始化灯光
            this.initLight();
            //初始化几何体
            //获取数据库中数据
            getStoreData().then(res=>{
              this.Store3DData=res.data.data;
              //存入本地缓存
              window.localStorage.setItem("Store3DData",JSON.stringify(this.Store3DData))
              for(var i=0;i<this.Store3DData.length;i++){
                this.buildDatas.push(this.Store3DData[i])
              }
              this.initObject();
            })
            //加载obj文件
            this.initAGV();
            //初始化后期效果通道
            this.initPass();
            //初始化效果组合器
            this.initComposer();
            //初始化控件
            this.initControls();
            //循环渲染
            this.animation();
          },
          initComposer(){
            this.renderPass = new RenderPass(scene,camera);
            composer = new EffectComposer(renderer);
            composer.addPass(this.renderPass);
            composer.addPass(this.outlinePass);
          },
          initPass(){
            //创建选中边框高亮的通道
            this.outlinePass = new OutlinePass(new THREE.Vector2(this.width,this.height),scene,camera);
            this.outlinePass.edgeStrength=10;//包围线浓度
            this.outlinePass.edgeGlow=0.1;//边缘线范围
            this.outlinePass.edgeThickness=1;//边缘线浓度
            this.outlinePass.pulsePeriod=2;//包围线闪烁频率
            this.outlinePass.visibleEdgeColor.set("#29e716")//包围线颜色
            this.outlinePass.hiddenEdgeColor.set("#190a05")//遮挡部分的边界线颜色
          },
          initThree(){
            renderer=new THREE.WebGLRenderer({
              antialias:true,
              alpha:true
              //用来解决模型重叠部分不停闪烁问题
              // logarithmicDepthBuffer: true
            });
            renderer.setSize(this.width,this.height);
            renderer.setClearColor(0x39609B);
            renderer.setPixelRatio(window.devicePixelRatio);
            document.getElementById("canvas-frame").appendChild(renderer.domElement);
            window.addEventListener("resize",this.onWindowResize,false);
          },
          initScene(){
            scene=new THREE.Scene();
          },
          initCamera(){
            camera=new THREE.PerspectiveCamera(
              60,
              this.width/this.height,
              1,10000
            );
            camera.position.set(0,1600,1000);
            camera.lookAt(0,0,0);
            scene.add(camera);
          },
          initLight(){
            //添加环境光
            amblight=new THREE.AmbientLight(0xffffff,1);
            amblight.position.set(0,0,0);
            scene.add(amblight);
            //添加平行光
            light=new THREE.DirectionalLight(0xffffff,0.3);
            light.position.set(0,200,0);
            scene.add(light);
            //添加点光源
            pointLight1=new THREE.PointLight(0xffffff,0.3);
            pointLight1.position.set(-500,200,0);
            pointLight2=new THREE.PointLight(0xffffff,0.3);
            pointLight2.position.set(500,200,0);
            scene.add(pointLight1);
            scene.add(pointLight2);
          },
          initObject(){
            //初始化地板====================
            let boxGeometry = new THREE.BoxGeometry(3400,1,1200);
            //材质对象
            var material = new THREE.MeshPhongMaterial({
              color: 0x5F7480,
            });
            let mesh = new THREE.Mesh(boxGeometry,material);
            mesh.name="floor";
            scene.add(mesh);

            //初始化墙体===================
            //正面
            let zmqt = new THREE.BoxGeometry(3400,160,20);
            let qtMaterial = new THREE.MeshPhongMaterial({
              color:0x96ABC8,
            });
            let zmmesh = new THREE.Mesh(zmqt,qtMaterial);
            zmmesh.position.set(0,80,600)
            zmmesh.name="wallfront";
            scene.add(zmmesh);
            //背面
            let bmqt = new THREE.BoxGeometry(3400,160,20);
            let bmmesh = new THREE.Mesh(bmqt,qtMaterial);
            bmmesh.position.set(0,80,-600)
            bmmesh.name="wallBehind";
            scene.add(bmmesh);
            //左侧
            let lmqt = new THREE.BoxGeometry(20,160,1200);
            let lmmesh = new THREE.Mesh(lmqt,qtMaterial);
            lmmesh.position.set(-1690,80,0)
            lmmesh.name="wallLeft"
            scene.add(lmmesh);
            //右侧
            let rmqt = new THREE.BoxGeometry(20,160,1200);
            let rmmesh = new THREE.Mesh(rmqt,qtMaterial);
            rmmesh.position.set(1690,80,0)
            rmmesh.name="wallRight"
            scene.add(rmmesh);
            //初始化小车移动路线
            let buildDataText = getBuildData().objects;
            for (let i=0;i<buildDataText.length;i++){
              let buildDataTextElement = buildDataText[i];
              switch(buildDataTextElement.objectType){
                case "route":
                  this.catmullRomCurve3 = Route(buildDataTextElement);
                  let line = RouteLine(this.catmullRomCurve3,buildDataTextElement);
                  scene.add(line);
              }
            }

            // 获取其他building的参数
            let buildData = this.buildDatas;
            for (let i=0;i<buildData.length;i++){
              let objectOption = buildData[i];
              //初始化库区
              let mesh1 = StoreArea(objectOption);
              this.objects.push(mesh1);
              scene.add(mesh1);
              //初始化库区对应的仓库
              let stores = objectOption.stores;
              for (let j=0;j<stores.length;j++){
                let store = stores[j];
                store.position=transPosition(store.position,objectOption.position);
                let mesh2 = Store(store);
                this.objects.push(mesh2)
                scene.add(mesh2)
                //初始化库区的echarts图标
                this.StoreSign(store);
                //初始化仓库中的每一组
                let groups = store.groups;
                for (let p=0;p<groups.length;p++){
                  let group = groups[p];
                  group.position=transPosition(group.position,store.position);
                  //初始化货架
                  let mesh3 = StoreShelf(group);
                  let mesh4 = StoreGroup(group,10);
                  this.objects.push(mesh3);
                  scene.add(mesh3);
                  this.objects.push(mesh4)
                  scene.add(mesh4);
                  //显示货架上的货物
                  let bins = group.bins;
                  for (let q=0;q<bins.length;q++){
                    let bin = bins[q];
                    //为了解决同一种类型的几何体重复创建（复用的原则）,在生成对象前前去进行一次判断
                    let number = judgmentObject(bin.state);
                    let mesh5 = Goods(group,bin,number);
                    mesh5.type="StoreGoods";
                    scene.add(mesh5);
                    this.objects.push(mesh5)
                  }

                }
              }
            }
          },
          initAGV(){
            let objLoader = new OBJLoader();
            let mtlLoader = new MTLLoader();
            mtlLoader.load('../../static/AGV.mtl',function (materials) {
                objLoader.setMaterials(materials);
                objLoader.load('../../static/AGV.obj',function (obj) {
                    obj.scale.set(0.1,0.1,0.1)
                    obj.traverse(function (child) {
                       if (child instanceof  THREE.Mesh){
                         child.geometry.applyMatrix4(new THREE.Matrix4().makeRotationY(Math.PI/2));
                         child.material.transparent=true
                       }
                    })
                    obj.position.set(-100,40,100)
                    CarObject=obj;
                    scene.add(obj);
                })
            })

          },
          StoreSign(option){
            let optionCube = {
              length: option.length,
              width: option.width,
              height: option.height,
              position: {
                x: option.position.x,
                y: option.position.y,
                z: option.position.z
              },
              style: {
                transparent:1,
                opacity:0.2,
                color: 0x17CEBC,
                depthTest:0
              },
            };
            let elementById = document.getElementById(option.no);
            let signChart=echarts.init(elementById);
            let optionChart = {
              title: {
                text: option.store_name,
                textStyle: {
                  color: '#fff',
                  fontSize: 30,
                  fontWeight: 'bold'
                },
                left: 'center',
                bottom: '42%',
              },
              tooltip: {
                show: false,
              },
              series: [{
                type: 'pie',
                radius: [0, "35%"],//饼图的半径，内半径和外半径
                data: [{
                  value: 0,
                  itemStyle: {
                    normal: {
                      color: "rgba(20,198,249,1)"
                    }
                  }
                }, ]
              },
              ]
            };
            signChart.setOption(optionChart);
            let signFihishchart=signChart;
            window.onresize = function(){
              signFihishchart.resize();
            }
            signChart.on('finished',function () {
              var spriteMap = new THREE.TextureLoader().load(signFihishchart.getDataURL());

              var spriteMaterial = new THREE.SpriteMaterial({
                transparent: true,
                map: spriteMap,
                side: THREE.DoubleSide
              });
              var sprite = new THREE.Sprite( spriteMaterial );
              sprite.uuid=option.no
              sprite.type='StoreSign';
              sprite.scale.set(250, 250, 1)
              let y= option.height+50;
              sprite.position.set(option.position.x, y, option.position.z);
              scene.add(sprite)
            });
          },
          initControls(){
            control=new OrbitControls(camera,renderer.domElement);
            //设置相机启动阻尼
            control.enableDamping=true
            control.dampingFactor = 0.5;
            // 视角最小距离
            control.minDistance = 0;
            // 视角最远距离
            control.maxDistance = 20000;
            // 最大角度
            control.maxPolarAngle = Math.PI / 2.2;

            stats=new Stats();
            document.body.appendChild(stats.dom)
            axes=new THREE.AxesHelper(1000);
            scene.add(axes);

            //初始化物体选中控件
            initObjectSelect(scene,camera,this.outlinePass);

          },
          onWindowResize(){
            camera.aspect = window.innerWidth / window.innerHeight;
            camera.updateProjectionMatrix();
            renderer.setSize( window.innerWidth, window.innerHeight );
          },
          animation(){
            requestAnimationFrame( this.animation );
            stats.update();
            //刷新小车位置，从而达到更新的目的
            this.moveCar();
            this.render();
          },
          moveCar(){
            if (this.catmullRomCurve3&&CarObject){
              this.carTime++;
              let points = this.catmullRomCurve3.getPoints(801);
              let point = points[this.carTime];
              let point1 = points[this.carTime+1];
              if(this.carTime>=800)
                this.carTime=0;
              if (point!==null&&point1!==null){
                CarObject.position.set(point.x,40,point.z);
                CarObject.lookAt(point1.x,40,point1.z);
              }
            }
          },
          render(){
            renderer.clear();
            // renderer.render(scene,camera);
            composer.render();

          },
          fpsClick(){
            if (stats.domElement.style.display === 'none')
              stats.domElement.style.display = 'block';
            else
              stats.domElement.style.display = 'none';
          },
          resetEvent(){
            control.reset();
          },
          storeClick(){
            if (this.storeIsShow===1){
            //  隐藏仓库对象(从场景中移除仓库对象)
              for(var i=0;i<this.objects.length;i++){
                let object = this.objects[i];
                if (object.type==="Store"){
                  scene.remove(object)
                }
              }
              this.storeIsShow=0;
            }else {
              for(var i=0;i<this.objects.length;i++){
                let object = this.objects[i];
                if (object.type==="Store"){
                  scene.add(object)
                }
              }
              this.storeIsShow=1;
            }
          },
          groupClick(){
            if (this.groupIsShow===1){
              //  隐藏仓库对象(从场景中移除仓库对象)
              for(var i=0;i<this.objects.length;i++){
                let object = this.objects[i];
                if (object.type==="StoreGroup"){
                  scene.remove(object)
                }
              }
              this.groupIsShow=0;
            }else {
              for(var i=0;i<this.objects.length;i++){
                let object = this.objects[i];
                if (object.type==="StoreGroup"){
                  scene.add(object)
                }
              }
              this.groupIsShow=1;
            }
          },
          shelfClick(){
            if (this.shelfIsShow===1){
              //  隐藏仓库对象(从场景中移除仓库对象)
              for(var i=0;i<this.objects.length;i++){
                let object = this.objects[i];
                if (object.type==="StoreShelf"){
                  scene.remove(object)
                }
              }
              this.shelfIsShow=0;
            }else {
              for(var i=0;i<this.objects.length;i++){
                let object = this.objects[i];
                if (object.type==="StoreShelf"){
                  scene.add(object)
                }
              }
              this.shelfIsShow=1;
            }
          }



        },



    }
</script>

<style scoped>
  div#canvas-frame{
    border: none;
    width: 100%;
    height: 1000px;
  }
  .sidebar{
    margin-top:100px;
    width: 1.5%;
    height:400px;
    border-radius:8px;
    text-align:center;
    background: rgba(205, 215, 230, 1);
    left: 10px;
    position: absolute;
    z-index: 1;
  }
  .buttonClass{
    width: 90%;
    border-radius: 50%;
    overflow: hidden;
    cursor: pointer;
    transition: all 0.6s;
    margin-top: 10px;
  }
  .buttonClass:hover{
    transform: scale(1.2);
  }
  #label {
    position: absolute;
    padding: 10px;
    background: rgba(255, 255, 255, 0.6);
    line-height: 1;
    color:#000000;
    border-radius: 5px;
    display:none;
  }
</style>
